/*
 * $Id: ActScheduledObjectDAO.java,v 1.13 2009/11/04 15:11:58 navdeep_mahajan Exp $
 * 
 * Copyright (C) 2009 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.common.database.dao;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.ASCUtil;
import com.ge.healthcare.autosc.common.database.pojo.ActRequest;
import com.ge.healthcare.autosc.common.database.pojo.ActScheduledObject;
import com.ge.healthcare.autosc.common.load.system.ISystemResource;
import com.ge.healthcare.autosc.common.message.converter.AutoSCMessage;
import com.ge.healthcare.autosc.common.pojo.TaskNResource;
import com.ge.healthcare.autosc.common.util.ApplicationInfo;
import com.ge.healthcare.autosc.common.util.PropertyConstants;
import com.ge.healthcare.autosc.common.util.TimeFormatStandard;

/**
 * @author 212042946
 * 
 */
public class ActScheduledObjectDAO extends BaseDAO implements
		IScheduledObjectDAO {

	/**
	 * Eclispe generated
	 */
	private static final long serialVersionUID = 3404265954214404758L;
	private ITaskDAO taskDAO;
	private IRequestDAO requestDAO;

	public ActScheduledObjectDAO() {
		super(ActScheduledObject.TABLE_NAME);
	}

	public ActScheduledObject schedule(AutoSCMessage ascMsg, Long timeAdjust) {
		ActScheduledObject scheduledObject = new ActScheduledObject();
		scheduledObject.setObjectId(ascMsg.getObjectId());
		scheduledObject.setObjectType(ascMsg.getObjectType());
		scheduledObject.setEnterDate(TimeFormatStandard.getNow());
		scheduledObject.setScheduledDate(TimeFormatStandard.getNow(timeAdjust));
		this.save(scheduledObject);
		return scheduledObject;
	}

	public ActScheduledObject getScheduledObjectByID(Long scheduledObjectId) {
		Object scheduledObject = findObjectByID(
				ActScheduledObject.COL_SCHEDULED_OBJECT_ID, scheduledObjectId);
		if (!ASCUtil.isNullOrEmptyObject(scheduledObject)) {
			return (ActScheduledObject) scheduledObject;
		}
		return null;
	}

	public List<ActScheduledObject> getScheduledObjectByObjectID(Long objectId) {
		List<?> rtvdScheduledObjects = findByProperty(
				ActScheduledObject.COL_OBJECT_ID, objectId);
		if (ASCUtil.isNullOrEmptyList(rtvdScheduledObjects)) {
			return null;
		}
		List<ActScheduledObject> scheduledObjectLst = new ArrayList<ActScheduledObject>();
		for (Object scheduledObject : rtvdScheduledObjects) {
			scheduledObjectLst.add((ActScheduledObject) scheduledObject);
		}
		return scheduledObjectLst;
	}

	/**
	 * Return the list of tasks that are now Pass their scheduled time. This
	 * should now only be used in testing scenarios as objects should only now
	 * be transmitted by the system when there are resources to execute them.
	 */
	public List<ActScheduledObject> getScheduledObjectPastNow() {
		StringBuffer query = queryScheduledObjectPastNow();
		ASCLogger.debug(this.getClass(), "getScheduledObjectPastNow",
				new StringBuffer().append(query));
		List<?> rtvdScheduledObjects = getHibernateTemplate().find(
				query.toString());
		List<ActScheduledObject> scheduledObjectLst = new ArrayList<ActScheduledObject>();
		if (ASCUtil.isNullOrEmptyList(rtvdScheduledObjects)) {
			return scheduledObjectLst;
		}
		for (Object scheduledObject : rtvdScheduledObjects) {
			scheduledObjectLst.add((ActScheduledObject) scheduledObject);
		}
		return scheduledObjectLst;
	}

	/**
	 * Get all scheduled passed due that could be consumed with the system
	 * resource object it has been given
	 * 
	 * @param systemResource
	 * @param codeName
	 * @return
	 */
	public List<AutoSCMessage> getAutoSCMessageObjects(
			ISystemResource systemResource, String codeName) {
		Long priority = Long.valueOf(ApplicationInfo.getInstance()
				.getLongPropertyValue(PropertyConstants.TASK_PRIORITY_LEVEL));
		if (ASCUtil.isNullOrEmptyObject(priority)) {
			throw new RuntimeException(
					"TASK_PRIORITY_LEVEL was not found property");
		}
		List<ActScheduledObject> schObjects = getScheduledObjectPastNow();
		List<AutoSCMessage> sendableObjs = new ArrayList<AutoSCMessage>();
		for (Iterator<ActScheduledObject> iterator = schObjects.iterator(); iterator
				.hasNext();) {
			ActScheduledObject schObj = iterator.next();
			if (schObj.isRequest()) {
				addRequest(sendableObjs, schObj, codeName);
			} else {
				// Get get Object
				TaskNResource task = taskDAO.getTaskNResource(schObj
						.getObjectId());
				if (!ASCUtil.isNullOrEmptyObject(task)) {
					if ((priority.compareTo(task.getPriority()) >= 0)
							&& systemResource.consume(task)) {
						// update the task code as sent.
						taskDAO.setCodeDetails(task.getActTask(), codeName);
						sendableObjs.add(task.getActTask());
					}
				} else {
					// Do not throw here
					StringBuffer msg = new StringBuffer();
					msg.append("Invalid Scheduled Object Found: ").append(
							schObj);
					ASCLogger.error(this.getClass(),
							"getScheduledObjectPastNow", new StringBuffer()
									.append(msg));
				}
			}
		}
		return sendableObjs;
	}

	private void addRequest(List<AutoSCMessage> sendableObjs,
			ActScheduledObject schObj, String codeName) {
		ActRequest request = requestDAO.getByRequestID(schObj.getObjectId());
		if (!ASCUtil.isNullOrEmptyObject(request)) {
			sendableObjs.add(request);
			requestDAO.setCodeDetails(request, codeName);
		} else {
			// Do not throw here
			StringBuffer msg = new StringBuffer();
			msg.append("Invalid Scheduled Object Found: ").append(schObj);
			ASCLogger.error(this.getClass(), "getScheduledObjectPastNow",
					new StringBuffer().append(msg));
		}
	}

	@SuppressWarnings("unchecked")
	public ActScheduledObject get(Long objectId, String objectType) {
		StringBuffer query = initQuery().append(" where ");
		query.append(ActScheduledObject.COL_OBJECT_ID);
		query.append(" = ? and ");
		query.append(ActScheduledObject.COL_OBJECT_TYPE);
		query.append(" = ? ");
		Object[] values = new Object[2];
		values[0] = objectId;
		values[1] = objectType;
		List<ActScheduledObject> lst = getHibernateTemplate().find(
				query.toString(), values);
		if (!ASCUtil.isNullOrEmptyList(lst)) {
			return lst.get(0);
		}
		return null;
	}

	public void delete(AutoSCMessage msg) {
		ActScheduledObject schObj = get(msg.getObjectId(), msg.getObjectType());
		if (!ASCUtil.isNullOrEmptyObject(schObj)) {
			deleteByID(schObj);
		}
	}

	/**
	 * @see com.ge.healthcare.autosc.common.database.dao.BaseDAO#save(java.lang.Object)
	 */
	public void save(Object pojo) {
		super.save(pojo);
	}

	/**
	 * @see com.ge.healthcare.autosc.common.database.dao.IRequestTypeDAO#saveAlways(java.lang.Object)
	 */
	public void saveAlways(Object pojo) {
		super.save(pojo);
	}

	/**
	 * @see com.ge.healthcare.autosc.common.database.dao.BaseDAO#deleteByID(java.lang.Object)
	 */
	public void deleteByID(Object pojo) {
		super.deleteByID(pojo);
	}

	/**
	 * @see com.ge.healthcare.autosc.common.database.dao.BaseDAO#refresh(java.lang.Object)
	 */
	public void refresh(Object pojo) {
		super.refresh(pojo);
	}

	private StringBuffer queryScheduledObjectPastNow() {
		StringBuffer query = initQuery().append(" where ");
		query.append(ActScheduledObject.COL_SCHEDULED_DATE);
		query.append(" <= current_date");
		return query;
	}

	/**
	 * @param taskDAO
	 *            the taskDAO to set
	 */
	public void setTaskDAO(ITaskDAO taskDAO) {
		this.taskDAO = taskDAO;
	}

	/**
	 * @param requestDAO
	 *            the requestDAO to set
	 */
	public void setRequestDAO(IRequestDAO requestDAO) {
		this.requestDAO = requestDAO;
	}

}
